﻿using Newtonsoft.Json.Linq;
using OrBitDataModule.Adaptor;
using OrBitDataModule.Base;
using OrBitDataModule.Common;
using OrBitDataModule.Contract;
using OrBitDataModule.Interface;
using OrBitDataModule.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace OrBitDataModule.Protocol
{
    [ProtocolType("Http服务")]
    public class HttpServerProvider : DataTaskBase
    {
        public HttpServerProvider(string uniqueId, string dataProtocolScriptId, string configJson, string taskName, string taskProtocolType, string apiName, string username, string password)
        {

            this.UniqueId = uniqueId;
            this.TaskName = taskName;
            this.TaskProtocolType = taskProtocolType;
            this.UserName = username;
            this.Password = password;
            this.ApiName = apiName;
            this.ConfigJson = configJson;
            this.DataProtocolScriptId = dataProtocolScriptId;
        }

        ~HttpServerProvider()
        {
            this.OnDispose();
        }
        public override IContext Context { get; set; }

        public override string UniqueId { get; }
        public override string ConfigJson { get; }
        public override Encoding DefaultEncoding { get; }

        public override string ScriptName { get; set; }
        public override string ScriptCode { get; set; }
        public override ScriptBase Script { get; set; }
        public override ScriptRunner ScripterRunner { get; set; }

        public override string DataProtocolScriptId { get; }

        public override bool IsScripDebug { get; set; }

        public override string TaskProtocolType { get; }

        public override string TaskName { get; }

        public override string UserName { get; }

        public override string Password { get; }

        public override string ApiName { get; }

        public override string Token { get; set; }
        public override int Expiration { get; set; }
        public override SerialPort SerialPortInstance { get; set; }
        public override SocketTcpClient TcpClientInstance { get; set; }

        private int port;

        private HttpServer httpServer = null;

        public override event EventHandler<TaskEventArgs> OnStateChange;

        public override void OnLoad()
        {
            try
            {
                var obj = JObject.Parse(ConfigJson);
                port = obj["Port"].Value<int>();
                httpServer = new HttpServer(port);
                httpServer.OnHttpError += HttpServer_OnHttpError;
                httpServer.OnHttpRequest += HttpServer_OnHttpRequest;
                this.ScripterRunner = new ScriptRunner();
                this.SettingProperty = new SettingDictionary(new { Port = port });
            }
            catch (Exception ex)
            {
                Script?.OnError(ex);
                WriteLog(ex.Message);
            }
        }

        public async override void Start()
        {
            try
            {
                OnStateChange?.Invoke(this, new TaskEventArgs(this.UniqueId, TaskRunningStatus.Starting));
                //获取最新的脚本代码
                if (!string.IsNullOrWhiteSpace(this.DataProtocolScriptId))
                {
                    var result = await ScriptApi.GetCodeAsync(this.DataProtocolScriptId);
                    this.ScriptName = result.ScriptName;
                    this.ScriptCode = result.ScriptCode;
                    CompileScript();
                    if (!this.CanRunScript)
                    {
                        OnStateChange?.Invoke(this, new TaskEventArgs(this.UniqueId, TaskRunningStatus.Stoped));
                        return;
                    }
                }

                Script?.OnLoad();
                httpServer.StartHttpServer();
                WriteLog($"已启动!");
                OnStateChange?.Invoke(this, new TaskEventArgs(this.UniqueId, TaskRunningStatus.Started));
                Script?.OnStarted();
            }
            catch (Exception ex)
            {
                Script?.OnError(ex);
                WriteLog(ex.Message);
                OnStateChange?.Invoke(this, new TaskEventArgs(this.UniqueId, TaskRunningStatus.Stoped));
            }
        }
        public override void Stop()
        {
            OnStateChange?.Invoke(this, new TaskEventArgs(this.UniqueId, TaskRunningStatus.Stopping));
            if (httpServer != null)
            {
                if (httpServer.IsListening)
                {
                    httpServer?.StopHttpServer();
                }
            }
            OnStateChange?.Invoke(this, new TaskEventArgs(this.UniqueId, TaskRunningStatus.Stoped));
        }

        private void HttpServer_OnHttpRequest(object sender, CustomEventHandler.HttpRequestEventArgs e)
        {
            Script?.OnHttpRequest(e.Request, e.Response);
        }


        private void HttpServer_OnHttpError(object sender, Exception e)
        {
            Script?.OnError(e);
        }

        public override string SendExternal(string message) => string.Empty;
        public override void OnDispose()
        {
            if (httpServer != null)
            {
                if (httpServer.IsListening)
                {
                    httpServer?.StopHttpServer();
                }
            }
            httpServer = null;
        }
    }
}
